package com.yy.wga.mp.module.pay.client;

import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.*;
import com.yy.wga.mp.module.pay.common.eunms.EPayChannel;
import com.yy.wga.mp.module.pay.client.request.wechat.WechatAppPreOrderRequest;
import com.yy.wga.mp.module.pay.client.request.wechat.WechatH5PreOrderRequest;
import com.yy.wga.mp.module.pay.client.request.wechat.WechatJsPreOrderRequest;
import com.yy.wga.mp.module.pay.client.request.wechat.WechatQueryOrderRequest;
import com.yy.wga.mp.module.pay.client.request.wechat.WechatRefundRequest;
import com.yy.wga.mp.module.pay.client.request.wechat.WechatTransferRequest;
import com.yy.wga.mp.module.pay.client.response.wechat.WechatAppPreOrderResponse;
import com.yy.wga.mp.module.pay.client.response.wechat.WechatH5PreOrderResponse;
import com.yy.wga.mp.module.pay.client.response.wechat.WechatJsPreOrderResponse;
import com.yy.wga.mp.module.pay.client.response.wechat.WechatQueryOrderResponse;
import com.yy.wga.mp.module.pay.client.response.wechat.WechatRefundResponse;
import com.yy.wga.mp.module.pay.client.response.wechat.WechatTransferResponse;
import com.yy.wga.common.core.exception.BusinessException;
import com.yy.wga.mp.common.interceptor.RequestUserHolder;
import com.yy.wga.mp.common.utils.common.IdUtils;
import com.yy.wga.mp.common.utils.common.JsonUtils;
import com.yy.wga.mp.common.utils.common.NumberUtils;
import com.yy.wga.mp.common.utils.common.StringUtils;
import com.yy.wga.mp.module.pay.client.enums.EPayOrderStatus;
import com.yy.wga.mp.module.pay.client.request.BasePreOrderRequest;
import com.yy.wga.mp.module.pay.client.request.BaseQueryOrderRequest;
import com.yy.wga.mp.module.pay.client.request.BaseRefundRequest;
import com.yy.wga.mp.module.pay.client.request.BaseTransferRequest;
import com.yy.wga.module.pay.client.request.wechat.*;
import com.yy.wga.mp.module.pay.client.response.BasePreOrderResponse;
import com.yy.wga.mp.module.pay.client.response.BaseQueryOrderResponse;
import com.yy.wga.mp.module.pay.client.response.BaseRefundResponse;
import com.yy.wga.mp.module.pay.client.response.BaseTransferResponse;
import com.yy.wga.module.pay.client.response.wechat.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.StringJoiner;

/**
 * @Author: gc
 * @Date: 2021/6/13
 * @Description: 微信支付
 **/
@Slf4j
@Component
@RequiredArgsConstructor
public class WechatPayClient implements PayClient {

    @Value("${spring.profiles.active}")
    private String profiles;

    /**
     * 应用id
     */
    @Value("${wxpay.appId}")
    private String appId;

    /**
     * 商户私钥
     */
    @Value("${wxpay.privateKeyPath}")
    private String privateKey;

    /**
     * 微信公钥
     */
    @Value("${wxpay.publicKey}")
    private String publicKey;

    /**
     * 商户号
     */
    @Value("${wxpay.mchId}")
    private String mchId;

    /**
     * 商户证书序列号
     */
    @Value("${wxpay.certSerialNo}")
    private String mchSerialNo;

    /**
     * V3密钥
     */
    @Value("${wxpay.apiV3Key}")
    private String apiV3Key;

    /**
     * 转账回调地址
     */
    @Value("${wechat.transfer.notify.url}")
    private String transferNotifyUrl;
    /**
     * 微信支付回调地址
     */
    @Value(value = "${wechat.pay.notify.url:}")
    private String notifyUrl;
    /**
     * 微信退款回调地址
     */
    @Value(value = "${wechat.refund.notify.url:}")
    private String refundUrl;

    private PrivateKey merchantPrivateKey;

    private CloseableHttpClient httpClient;
    public TransferBatchService transferBatchService;
    /**
     * 创建预订单链接--APP
     */
    private final static String APP_CREATE_ORDER_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";
    /**
     * 创建预订单链接--H5
     */
    private final static String H5_CREATE_ORDER_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5";
    /**
     * 创建预订单链接--js
     */
    private final static String JS_CREATE_ORDER_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
    /**
     * 微信支付订单号查询订单请求地址
     */
    private final static String QUERY_ORDER_TRANSACTION_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s";
    /**
     * 商户订单号查询订单请求地址
     */
    private final static String QUERY_ORDER_OUTTRADENO_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s";
    /**
     * 退款请求地址
     */
    private final static String REFUND_URL = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";


    private final ResourceLoader resourceLoader;
    @PostConstruct
    public void initPostConstruct() {
        try (InputStream inputStream = resourceLoader.getResource("classpath:" + privateKey).getInputStream()){
            merchantPrivateKey = PemUtil.loadPrivateKey(inputStream);
            PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, merchantPrivateKey);
            AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                    new WechatPay2Credentials(mchId, privateKeySigner), apiV3Key.getBytes(StandardCharsets.UTF_8));
            // 初始化httpClient
            this.httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(verifier))
                    .build();
            log.info("初始化微信支付客户端完成");

            // 初始化转账
            Config config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(mchId)
                    .privateKey(merchantPrivateKey)
                    .merchantSerialNumber(mchSerialNo)
                    .apiV3Key(apiV3Key)
                    .build();
            transferBatchService = new TransferBatchService.Builder().config(config).build();
            log.info("初始化微信转账客户端完成");
        } catch (Exception e) {
            log.error("微信支付客户端初始化失败,{}", e.getMessage(), e);
//            throw new BusinessException("微信支付客户端初始化失败,{}", e.getMessage());
        }
    }

    @Override
    public Integer getType() {
        return EPayChannel.WECHAT.getType();
    }

    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
     * @param request 请求参数
     * @param <T>
     * @return
     */
    @Override
    public <T extends BasePreOrderResponse> T appPreOrder(BasePreOrderRequest<T> request) {
        if (!(request instanceof WechatAppPreOrderRequest)) {
            throw new BusinessException("请求参数实体错误");
        }
        WechatAppPreOrderRequest tradeAppPayRequestDTO = (WechatAppPreOrderRequest)request;
        tradeAppPayRequestDTO.setAppId(appId);
        tradeAppPayRequestDTO.setMchId(mchId);
        if (tradeAppPayRequestDTO.getNotifyUrl() != null) {
            tradeAppPayRequestDTO.setNotifyUrl(tradeAppPayRequestDTO.getNotifyUrl() + RequestUserHolder.getBaseRequest().getAppKey() + "/" + mchId);
        }

        // 请求URL
        HttpPost httpPost = new HttpPost(APP_CREATE_ORDER_URL);
        // 请求body参数
        StringEntity stringEntity = new StringEntity(JsonUtils.toJSONString(tradeAppPayRequestDTO), "UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        HttpEntity entity = null;
        try {
            log.info("预订单请求参数，{}", JsonUtils.toJSONString(tradeAppPayRequestDTO));
            HttpResponse response = httpClient.execute(httpPost);
            log.info("预订单请求结果，code={},body={}", response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity()));
            int statusCode = response.getStatusLine().getStatusCode();
            //处理成功
            if (statusCode == HttpStatus.SC_OK) {
                entity = response.getEntity();
                JSONObject responseJsonObject = JsonUtils.parseObject(EntityUtils.toString(entity));
                // 响应结果封装
                if (responseJsonObject != null) {
                    WechatAppPreOrderResponse createResponse = new WechatAppPreOrderResponse();
                    createResponse.setPrepayId(responseJsonObject.getString("prepay_id"));
                    createResponse.setPackageValue("Sign=WXPay");
                    createResponse.setNonceStr(IdUtils.genRandomString(32));
                    createResponse.setTimeStamp(System.currentTimeMillis() / 1000);
                    createResponse.setAppId(appId);
                    createResponse.setMchId(mchId);
                    // 加密请求信息拼接
                    StringJoiner sj = new StringJoiner("\n");
                    String signMessage = sj.add(appId)
                            .add(createResponse.getTimeStamp().toString())
                            .add(createResponse.getNonceStr())
                            .add(createResponse.getPrepayId()).toString() + "\n";
                    createResponse.setSign(this.getSign(signMessage));
                    return (T) createResponse;
                }
            }
        } catch (Exception e) {
            log.error("创建微信支付订单失败", e);
            throw new BusinessException(EResponseCode.SYSTEM_BUSY_ERROR);
        } finally {
            if (entity != null) {
                EntityUtils.consumeQuietly(entity);
            }
        }
        throw new BusinessException("预订单生成失败，请重试一下");
    }

    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml
     * @param request 请求参数
     * @param <T>
     * @return
     */
    @Override
    public <T extends BasePreOrderResponse> T h5PreOrder(BasePreOrderRequest<T> request) {
        if (!(request instanceof WechatH5PreOrderRequest)) {
            throw new BusinessException("请求参数实体错误");
        }

        WechatH5PreOrderRequest tradeAppPayRequestDTO = (WechatH5PreOrderRequest)request;
        tradeAppPayRequestDTO.setAppId(appId);
        tradeAppPayRequestDTO.setMchId(mchId);
        if (tradeAppPayRequestDTO.getNotifyUrl() != null) {
            tradeAppPayRequestDTO.setNotifyUrl(tradeAppPayRequestDTO.getNotifyUrl() + "/" + mchId);
        }

        // 请求URL
        HttpPost httpPost = new HttpPost(H5_CREATE_ORDER_URL);
        // 请求body参数
        StringEntity stringEntity = new StringEntity(JsonUtils.toJSONString(tradeAppPayRequestDTO), "UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        HttpEntity entity = null;
        try {
            log.info("预订单请求参数，{}", JsonUtils.toJSONString(tradeAppPayRequestDTO));
            HttpResponse response = httpClient.execute(httpPost);
            log.info("预订单请求结果，code={},body={}", response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity()));
            int statusCode = response.getStatusLine().getStatusCode();
            //处理成功
            if (statusCode == HttpStatus.SC_OK) {
                entity = response.getEntity();
                JSONObject responseJsonObject = JsonUtils.parseObject(EntityUtils.toString(entity));
                // 响应结果封装
                if (responseJsonObject != null) {
                    WechatH5PreOrderResponse createResponse = new WechatH5PreOrderResponse();
                    String h5Url = responseJsonObject.getString("h5_url");
                    createResponse.setH5Url(h5Url);
                    createResponse.setAppId(appId);
                    return (T) createResponse;
                }
            }
        } catch (Exception e) {
            log.error("创建微信支付订单失败", e);
            throw new BusinessException(EResponseCode.SYSTEM_BUSY_ERROR);
        } finally {
            if (entity != null) {
                EntityUtils.consumeQuietly(entity);
            }
        }
        throw new BusinessException("预订单生成失败，请重试一下");
    }

    @Override
    public <T extends BasePreOrderResponse> T jsPreOrder(BasePreOrderRequest<T> request) {
        if (!(request instanceof WechatJsPreOrderRequest)) {
            throw new BusinessException("请求参数实体错误");
        }
        WechatJsPreOrderRequest tradeAppPayRequestDTO = (WechatJsPreOrderRequest)request;
        tradeAppPayRequestDTO.setAppId(appId);
        tradeAppPayRequestDTO.setMchId(mchId);
        tradeAppPayRequestDTO.setNotifyUrl(notifyUrl + RequestUserHolder.getBaseRequest().getAppKey() + "/" + appId);
        // 请求URL
        HttpPost httpPost = new HttpPost(JS_CREATE_ORDER_URL);
        // 请求body参数
        StringEntity stringEntity = new StringEntity(JsonUtils.toJSONString(tradeAppPayRequestDTO), "UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        HttpEntity entity = null;
        try {
            log.info("预订单请求参数，{}", JsonUtils.toJSONString(tradeAppPayRequestDTO));
            HttpResponse response = httpClient.execute(httpPost);
            log.info("预订单请求结果，code={},body={}", response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity()));
            int statusCode = response.getStatusLine().getStatusCode();
            //处理成功
            if (statusCode == HttpStatus.SC_OK) {
                entity = response.getEntity();
                JSONObject responseJsonObject = JsonUtils.parseObject(EntityUtils.toString(entity));
                // 响应结果封装
                if (responseJsonObject != null) {
                    WechatJsPreOrderResponse createResponse = new WechatJsPreOrderResponse();
                    String prepayId = responseJsonObject.getString("prepay_id");
                    createResponse.setAppId(appId);
                    createResponse.setMchId(mchId);
                    createResponse.setPrepayId("prepay_id=" + prepayId);
                    createResponse.setNonceStr(IdUtils.uuid());
                    createResponse.setTimeStamp(System.currentTimeMillis() / 1000);
                    // 加密请求信息拼接
                    StringJoiner sj = new StringJoiner("\n");
                    String signMessage = sj.add(appId)
                            .add(createResponse.getTimeStamp().toString())
                            .add(createResponse.getNonceStr())
                            .add(createResponse.getPrepayId()) + "\n";
                    createResponse.setPaySign(this.getSign(signMessage));
                    return (T) createResponse;
                }
            }
        } catch (Exception e) {
            log.error("创建微信支付订单失败", e);
            throw new BusinessException(EResponseCode.SYSTEM_BUSY_ERROR);
        } finally {
            if (entity != null) {
                EntityUtils.consumeQuietly(entity);
            }
        }
        throw new BusinessException("预订单生成失败，请重试一下");
    }

    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_2.shtml
     * @param request 请求参数
     * @param <T>
     * @return
     */
    @Override
    public <T extends BaseQueryOrderResponse> T queryOrder(BaseQueryOrderRequest<T> request) {
        if (!(request instanceof WechatQueryOrderRequest)) {
            throw new BusinessException("请求参数实体错误");
        }
        WechatQueryOrderRequest queryOrderRequest = (WechatQueryOrderRequest)request;

        //请求URL，优先使用微信订单号
        String url = null;
        if (StringUtils.isNotBlank(queryOrderRequest.getTransactionId())) {
            url = String.format(WechatPayClient.QUERY_ORDER_TRANSACTION_URL, queryOrderRequest.getTransactionId(), mchId);
        } else if (StringUtils.isNotBlank(queryOrderRequest.getOutTradeNo())){
            url = String.format(WechatPayClient.QUERY_ORDER_OUTTRADENO_URL, queryOrderRequest.getOutTradeNo(), mchId);
        } else {
            throw new BusinessException("查询订单号不能为空");
        }

        //完成签名并执行请求
        HttpGet httpGet = new HttpGet(url);
        httpGet.addHeader("Accept", "application/json");
        try {
            log.info("查询订单请求参数，{}", url);
            HttpResponse response = httpClient.execute(httpGet);
            log.info("查询订单请求结果，code={},body={}", response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity()));
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                WechatQueryOrderResponse queryOrderResponse = JSONObject.parseObject(EntityUtils.toString(response.getEntity()), WechatQueryOrderResponse.class);
                return (T) queryOrderResponse;
            }
        } catch (Exception e) {
            log.error("查询微信支付订单失败", e);
        }
        throw new BusinessException(EResponseCode.SYSTEM_BUSY_ERROR);
    }

    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_9.shtml
     * @param request 请求参数
     * @return 响应结果
     */
    @Override
    public <T extends BaseRefundResponse> T refund(BaseRefundRequest<T> request) {
        if (!(request instanceof WechatRefundRequest)) {
            throw new BusinessException("请求参数实体错误");
        }
        WechatRefundRequest refundRequest = (WechatRefundRequest)request;
        refundRequest.setNotifyUrl(refundUrl + RequestUserHolder.getBaseRequest().getAppKey() + "/" + appId);
        // 请求URL
        HttpPost httpPost = new HttpPost(REFUND_URL);
        // 请求body参数
        StringEntity stringEntity = new StringEntity(JsonUtils.toJSONString(refundRequest), "UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        HttpEntity entity = null;

        try {
            log.info("微信退款请求参数，{}", JsonUtils.toJSONString(refundRequest));
            HttpResponse response = httpClient.execute(httpPost);
            String resultJson = EntityUtils.toString(response.getEntity());
            log.info("微信退款请求结果，code={},body={}", response.getStatusLine().getStatusCode(), resultJson);
            int statusCode = response.getStatusLine().getStatusCode();
            entity = response.getEntity();
            WechatRefundResponse refundResponse = JsonUtils.parseObject(resultJson, WechatRefundResponse.class);
            //处理成功
            if (statusCode == HttpStatus.SC_OK) {
                // 响应结果封装
                if (refundResponse != null) {
                    return (T) refundResponse;
                }
            } else {
                throw new BusinessException(refundResponse.getMessage());
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("创建微信支付订单失败", e);
            throw new BusinessException(EResponseCode.SYSTEM_BUSY_ERROR);
        } finally {
            if (entity != null) {
                EntityUtils.consumeQuietly(entity);
            }
        }
        throw new BusinessException("退款失败，请重试一下");
    }

    @Override
    public <T extends BaseTransferResponse> T transfer(BaseTransferRequest<T> request) {
        if (!(request instanceof WechatTransferRequest)) {
            throw new BusinessException("请求参数实体错误");
        }
        WechatTransferRequest wechatTransferRequest = (WechatTransferRequest) request;
        InitiateBatchTransferRequest initiateBatchTransferRequest =
                new InitiateBatchTransferRequest();
        initiateBatchTransferRequest.setAppid(appId);
        initiateBatchTransferRequest.setOutBatchNo(wechatTransferRequest.getOrderNo());
        initiateBatchTransferRequest.setBatchName(wechatTransferRequest.getTitle());
        initiateBatchTransferRequest.setBatchRemark(wechatTransferRequest.getRemark());
        long amount = NumberUtils.changeY2F(wechatTransferRequest.getAmount().doubleValue());
        initiateBatchTransferRequest.setTotalAmount(amount);
        initiateBatchTransferRequest.setTotalNum(1);

        List<TransferDetailInput> transferDetailListList = new ArrayList<>();
        TransferDetailInput transferDetailInput = new TransferDetailInput();
        transferDetailInput.setOutDetailNo(wechatTransferRequest.getOrderNo());
        transferDetailInput.setTransferAmount(amount);
        transferDetailInput.setTransferRemark(wechatTransferRequest.getRemark());
        transferDetailInput.setOpenid(wechatTransferRequest.getOpenId());
        // rsa
        transferDetailInput.setUserName(rsaEncryptOAEP(wechatTransferRequest.getName(), publicKey));
        transferDetailListList.add(transferDetailInput);
        initiateBatchTransferRequest.setTransferDetailList(
                transferDetailListList);

        initiateBatchTransferRequest.setTransferSceneId("1000");
        initiateBatchTransferRequest.setNotifyUrl(transferNotifyUrl + RequestUserHolder.getBaseRequest().getAppKey() + "/" + appId);
        InitiateBatchTransferResponse transferResponse =
                transferBatchService.initiateBatchTransfer(initiateBatchTransferRequest);
        WechatTransferResponse response = new WechatTransferResponse();
        response.setAppId(appId);
        response.setChannelOrderNo(transferResponse.getBatchId());
        response.setOutTradeNo(wechatTransferRequest.getOrderNo());
        String batchStatus = transferResponse.getBatchStatus();
        EPayOrderStatus payOrderStatus = EPayOrderStatus.WAIT;
        if ("FINISHED".equals(batchStatus)) {
            payOrderStatus = EPayOrderStatus.SUCCESS;
        } else if ("CLOSED".equals(batchStatus)) {
            payOrderStatus = EPayOrderStatus.CANCEL;
        }
        response.setStatus(payOrderStatus);
        return (T) response;
    }

    /**
     * 查询转账明细
     * @param request 请求参数实体
     * @return
     */
    public TransferDetailEntity queryTransferDetail(GetTransferDetailByOutNoRequest request) {
        return transferBatchService.getTransferDetailByOutNo(request);
    }

    /**
     * 内容加密
     * @param signMessage 加密内容
     * @return
     * @throws Exception
     */
    public String getSign(String signMessage) throws Exception {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(merchantPrivateKey);
        sign.update(signMessage.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 获取apiV3Key
     *
     * @return apiV3Key
     */
    public String getApiV3Key() {
        return apiV3Key;
    }

    /**
     * 加密
     * @param message
     * @param publicKey
     * @return
     */
    public static String rsaEncryptOAEP(String message, String publicKey) {
        try {
            final byte[] keyBytes = org.apache.commons.codec.binary.Base64.decodeBase64(publicKey);
            final X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            final KeyFactory keyFactory = KeyFactory.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            final Key publicK = keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicK);
            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] cipherdata = cipher.doFinal(data);
            return Base64.getEncoder().encodeToString(cipherdata);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException("无效的公钥", e);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new BusinessException("加密原串的长度不能超过214字节");
        } catch (InvalidKeySpecException e) {
            throw new BusinessException("无限的key");
        }
    }
}

